拓扑排序算法实现



查看原文:http://www.wyblog.cn/2016/12/05/%e6%8b%93%e6%89%91%e6%8e%92%e5%ba%8f%e7%ae%97%e6%b3%95%e5%ae%9e%e7%8e%b0/

拓扑排序,是将一个有向无环图DAG中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。具体可参考百科。 我这里算法核心思想是先用邻接表实现一个DAG图,同时计算图里所有顶点的入度。首先将度为零的顶点全部入队列,然后不断从队列里弹出入度为0的顶点,再把与这个顶点邻接的所有定点给加入队列,直到最后队列为空。这里要注意的是要设置一个counter变量计数,用来检查生成的图是否存在环。 算法思想纯参考《数据结构与算法》这本书里的伪代码。 具体实现如下:


#include<cstdio> #include<iostream> #include<queue> #define MAX_VERTEX_NUM 100 #define Vertextype int using namespace std; typedef struct ArcNode //邻接表里的邻接点 { int adjVertex; ArcNode *nextEdgeNode; }ArcNode; typedef struct VerNode //DAG图顶点 { int indeed; Vertextype data; ArcNode *firstedge; }VerNode; typedef struct Graph { VerNode verNode[MAX_VERTEX_NUM]; int vertex_num,edge_num; }Graph; void CreateDAG(Graph &G,int n,int e) { int i,j,k; G.vertex_num=n; G.edge_num=e; for(i=1;i<=n;i++) //初始化所有顶点 { cin>>G.verNode[i].data; G.verNode[i].firstedge=NULL; G.verNode[i].indeed=0; } for(k=1;k<=e;k++) { ArcNode *p; p=new ArcNode; cin>>i>>j; p->adjVertex=j; p->nextEdgeNode=G.verNode[i].firstedge; //头部插入 G.verNode[i].firstedge=p; G.verNode[j].indeed+=1; //入度计算 } } void Topsort(Graph &G) { int i; queue<VerNode> Q; int counter=0; VerNode V; ArcNode *w; for(i=1;i<=G.vertex_num;i++) if(G.verNode[i].indeed==0) Q.push(G.verNode[i]); cout<<"The topsort is: "; while(!Q.empty()) { V=Q.front();Q.pop(); cout<<V.data<<" "; counter++; w=V.firstedge; while(w) { G.verNode[w->adjVertex].indeed--; if(G.verNode[w->adjVertex].indeed==0) Q.push(G.verNode[w->adjVertex]); w=w->nextEdgeNode; } } if(counter<G.vertex_num) cout<<"Graph has a cycle!"<<endl; } int main(void) { Graph G; CreateDAG(G,7,12); //这里明确给出DAG含多少个顶点、多少条边 Topsort(G); }

以下是vector容器实现的拓扑排序,程序精简了许多,参考自博客:

http://blog.csdn.net/lrgdongnan/article/details/51679781


#include <iostream> #include <stack> #include <vector> #include <list> using namespace std; vector<list<int>> Adj; //邻接表 vector<int> inDegree; //保存每个节点的入度 stack<int> stk; //保存当前入度为0的节点编号 void CreatGraph() { int n, m, v1, v2; cin >> n >> m; Adj.assign(n, list<int>()); inDegree.assign(n, 0); while (m--) { cin >> v1 >> v2; Adj[v1].push_back(v2); inDegree[v2]++; } for (int i = 0; i < n;i++) if (inDegree[i] == 0) stk.push(i); } void tpSort() { vector<int> vec; int v; while (!stk.empty()) { v = stk.top(); stk.pop(); //inDegree[v] = -1; //遍历与节点v相连的节点 for (auto it = Adj[v].begin(); it != Adj[v].end(); it++) { inDegree[*it]--; if (inDegree[*it] == 0) stk.push(*it); } //Adj[v].clear(); //本行可以省略,以提升程序效率 vec.push_back(v); } if (vec.size() != inDegree.size()) { cout << "图中存在环路,不能进行拓扑排序!\n"; return; } for (auto item : vec) cout << item << " "; cout << endl; } int main() { CreatGraph(); tpSort(); system("pause"); return 0; }


查看原文:http://www.wyblog.cn/2016/12/05/%e6%8b%93%e6%89%91%e6%8e%92%e5%ba%8f%e7%ae%97%e6%b3%95%e5%ae%9e%e7%8e%b0/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值